/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/*******************************************************************************
    FILE NAME:		ecanbaseioctl.h

    PROJECT:		Linux ECAN527/1000 driver, library, and sample programs

    FILE DESCRIPTION:	This header file contains the low level ioctl
    			definitions.

    Copyright (c) 2004 RTD Embedded Technologies, Inc.

    For driver version, compiler, and target information, please refer to the
    file README.TXT.
*******************************************************************************/

#ifndef _ECAN_BASE_IOCTL_H
#define _ECAN_BASE_IOCTL_H


#ifndef __KERNEL__
 #include <sys/ioctl.h>
#else
 #include <linux/ioctl.h>
#endif

#include "ecan_types.h"

typedef unsigned long long int ulonglong;

/*
Full device name composed from following components:
	RTD_ECAN_DEVICE_NAME_BASE
	RTD_ECAN*_MAGIC_NUMBER
	minus sign ("-")
	board (minor) decimal number
*/

#ifndef  RTD_ECAN_DEVICE_NAME_BASE
#define RTD_ECAN_DEVICE_NAME_BASE "/dev/rtd-ecan"
#endif

#define RTD_ECAN1000_MAGIC_NUMBER 1000
#define RTD_ECAN527_MAGIC_NUMBER   527

#define RTD_ECAN_DEVICE_MAX_NAME_LENGTH \
    (sizeof(RTD_ECAN_DEVICE_NAME_BASE) + 6 + 1 + 3)


#define RTD_ECAN_DEFAULT_MAX_RX_QUEUE_SIZE 1000U
#define RTD_ECAN_DEFAULT_MAX_TX_QUEUE_SIZE 1000U


static inline
u32_t rtd_ecan_convert_octets_to_id( int extended, const u8_t octets[4] )
{
    u32_t ret =    ( ((u32_t)octets[0] & 0xff)   << 8 ) | (octets[1] & 0xff);
    if( extended )
	ret = ( ((ret<<8) | (octets[2] & 0xff) ) << 8 ) | (octets[3] & 0xff);
    return ret;
}

static inline
void rtd_ecan_convert_id_to_octets( int extended, u32_t id, u8_t octets[4] )
{
    if( extended )
    {
	octets[3] = id & 0xff; id >>= 8;
	octets[2] = id & 0xff; id >>= 8;
    }
	octets[1] = id & 0xff; id >>= 8;
	octets[0] = id & 0xff;
}


/* free slot from linux/Documentation/ioctl-number.txt */
enum { __RTD_ECAN_IOCTL_TYPE='Z' };


enum	/* __rtd_ecan_ioctl_number */
{
    __RTD_ECAN_IOCTL_NUMBER__GET_DRIVER_VERSION,
    __RTD_ECAN_IOCTL_NUMBER__GET_BOARD_NAME,

    __RTD_ECAN_IOCTL_NUMBER__SET_BUS_CONFIG,
    __RTD_ECAN_IOCTL_NUMBER__SEND_COMMAND,
    __RTD_ECAN_IOCTL_NUMBER__SET_LEDS,
    __RTD_ECAN_IOCTL_NUMBER__GET_RAM,
    __RTD_ECAN_IOCTL_NUMBER__SET_RAM,

    __RTD_ECAN_IOCTL_NUMBER__SET_RX_MAX_QUEUE_SIZE,
    __RTD_ECAN_IOCTL_NUMBER__SET_TX_MAX_QUEUE_SIZE,
    __RTD_ECAN_IOCTL_NUMBER__CLEAR_QUEUES,
    __RTD_ECAN_IOCTL_NUMBER__GET_QUEUES_COUNTS,

    __RTD_ECAN_IOCTL_NUMBER__STOP,
    __RTD_ECAN_IOCTL_NUMBER__START,
    __RTD_ECAN_IOCTL_NUMBER__TEST,

    __RTD_ECAN_IOCTL_NUMBER__PREPARE_RECEIVED_MESSAGE,
    __RTD_ECAN_IOCTL_NUMBER__GET_STATUS,
    __RTD_ECAN_IOCTL_NUMBER__RECV_MESSAGE,
    __RTD_ECAN_IOCTL_NUMBER__SEND_MESSAGE,
    __RTD_ECAN_IOCTL_NUMBER__SETUP_MESSAGE_OBJECT,
    __RTD_ECAN_IOCTL_NUMBER__SET_FILTER,
    __RTD_ECAN_IOCTL_NUMBER__SET_EVENTS_MASK,

    __RTD_ECAN_IOCTL_NUMBER__GET_ACCOUNTS,
    __RTD_ECAN_IOCTL_NUMBER__CLEAR_ACCOUNTS,
    __RTD_ECAN_IOCTL_NUMBER__READ_DIGITAL_IO,
    __RTD_ECAN_IOCTL_NUMBER__WRITE_DIGITAL_IO,
    __RTD_ECAN_IOCTL_NUMBER__LOAD_PORT_BIT_DIR,
    __RTD_ECAN_IOCTL_NUMBER__ALLOW_BUFFER_OVERWRITE,
};


/* build ioctl code */
#define __RTD_ECAN_IOC(ioctl_number) \
	_IOC(_IOC_NONE, __RTD_ECAN_IOCTL_TYPE, (ioctl_number), 0)


/* use size field of ioctl code for extra parameter */
enum
{
    __RTD_ECAN_DONT_USE_QUEUE  = 1 << _IOC_SIZESHIFT
};


enum	/* __rtd_ecan_ioctl */
{
    __RTD_ECAN_IOCTL__GET_DRIVER_VERSION =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__GET_DRIVER_VERSION)   ,

    __RTD_ECAN_IOCTL__GET_BOARD_NAME     =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__GET_BOARD_NAME)       ,


    __RTD_ECAN_IOCTL__SET_BUS_CONFIG =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SET_BUS_CONFIG)       ,

    __RTD_ECAN_IOCTL__SEND_COMMAND   =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SEND_COMMAND)         ,

    __RTD_ECAN_IOCTL__SET_LEDS       =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SET_LEDS)             ,

    __RTD_ECAN_IOCTL__GET_RAM        =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__GET_RAM)              ,

    __RTD_ECAN_IOCTL__SET_RAM        =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SET_RAM)              ,


    __RTD_ECAN_IOCTL__SET_RX_MAX_QUEUE_SIZE =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SET_RX_MAX_QUEUE_SIZE),

    __RTD_ECAN_IOCTL__SET_TX_MAX_QUEUE_SIZE =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SET_TX_MAX_QUEUE_SIZE),

    __RTD_ECAN_IOCTL__CLEAR_QUEUES          =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__CLEAR_QUEUES)         ,

    __RTD_ECAN_IOCTL__GET_QUEUES_COUNTS     =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__GET_QUEUES_COUNTS)    ,


    __RTD_ECAN_IOCTL__STOP           =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__STOP)                 ,

    __RTD_ECAN_IOCTL__START          =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__START)                ,

    __RTD_ECAN_IOCTL__TEST           =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__TEST)                 ,


    __RTD_ECAN_IOCTL__PREPARE_RECEIVED_MESSAGE =
	__RTD_ECAN_IOC(
	    __RTD_ECAN_IOCTL_NUMBER__PREPARE_RECEIVED_MESSAGE)        ,

    __RTD_ECAN_IOCTL__GET_STATUS           =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__GET_STATUS)           ,

    __RTD_ECAN_IOCTL__RECV_MESSAGE         =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__RECV_MESSAGE)         ,

    __RTD_ECAN_IOCTL__SEND_MESSAGE         =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SEND_MESSAGE)         ,

    __RTD_ECAN_IOCTL__SETUP_MESSAGE_OBJECT =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SETUP_MESSAGE_OBJECT) ,

    __RTD_ECAN_IOCTL__SET_FILTER           =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__SET_FILTER)           ,

    __RTD_ECAN_IOCTL__SET_EVENTS_MASK      =
	__RTD_ECAN_IOC(
	    __RTD_ECAN_IOCTL_NUMBER__SET_EVENTS_MASK)                 ,


    __RTD_ECAN_IOCTL__GET_ACCOUNTS         =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__GET_ACCOUNTS)         ,

    __RTD_ECAN_IOCTL__CLEAR_ACCOUNTS       =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__CLEAR_ACCOUNTS)       ,

    __RTD_ECAN_IOCTL__READ_DIGITAL_IO =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__READ_DIGITAL_IO),

    __RTD_ECAN_IOCTL__WRITE_DIGITAL_IO =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__WRITE_DIGITAL_IO),

    __RTD_ECAN_IOCTL__LOAD_PORT_BIT_DIR =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__LOAD_PORT_BIT_DIR),

    __RTD_ECAN_IOCTL__ALLOW_BUFFER_OVERWRITE =
	__RTD_ECAN_IOC(__RTD_ECAN_IOCTL_NUMBER__ALLOW_BUFFER_OVERWRITE),
};


/******************************************************************************
 * __rtd_ecan_ioctl_busconfig                                                 *
 *                                                                            *
 * Used to pass data into ioctl(__RTD_ECAN_IOCTL__SET_BUS_CONFIG)             *
 ******************************************************************************/

struct __rtd_ecan_ioctl_busconfig
{

    /*
     * Device specific value for Bus Timing Register 0
     */

    u8_t BusTiming0;

    /*
     * Device specific value for Bus Timing Register 1
     */

    u8_t BusTiming1;

    /*
     * Value for Clock Divider Register (ECAN1000) or Clockout Register
     * (ECAN527).  A value of 0 means do not change.
     */

    u8_t ClockOut;

    /*
     * Value for Output Control Register (ECAN1000) or Bus Configuration
     * Register (ECAN527).  A value of 0xff means set default configuration.
     */

    u8_t BusConfig;
};


/******************************************************************************
 * __rtd_ecan_ioctl_get_ram                                                   *
 *                                                                            *
 * Used to return data from ioctl(__RTD_ECAN_IOCTL__GET_RAM)                  *
 ******************************************************************************/

struct __rtd_ecan_ioctl_get_ram
{

    /*
     * Byte offset from beginning of board's I/O space where read should occur
     */

    size_t ram_offset;

    /*
     * Number of bytes to transfer
     */

    size_t ram_length;

    /*
     * Address of buffer where data read will be stored
     */

    void* user_buffer;
};


/******************************************************************************
 * __rtd_ecan_ioctl_set_ram                                                   *
 *                                                                            *
 * Used to pass data into ioctl(__RTD_ECAN_IOCTL__SET_RAM)                    *
 ******************************************************************************/

struct __rtd_ecan_ioctl_set_ram
{

    /*
     * Byte offset from beginning of board's I/O space where write should occur
     */

    size_t ram_offset;

    /*
     * Number of bytes to transfer
     */

    size_t ram_length;

    /*
     * Address of buffer where data to write is stored
     */

    const void* user_buffer;
};


/******************************************************************************
 * __rtd_ecan_ioctl_queues_counts                                             *
 *                                                                            *
 * Used to return data from ioctl(__RTD_ECAN_IOCTL__GET_QUEUES_COUNTS)        *
 ******************************************************************************/

struct __rtd_ecan_ioctl_queues_counts
{

    /*
     * Number of message items in driver's receive queue
     */

    size_t rx_queue_count;

    /*
     * Number of message items in driver's transmit queue
     */

    size_t tx_queue_count;
};


/******************************************************************************
 * __rtd_ecan_ioctl_prepare_received_message                                  *
 *                                                                            *
 * Used to return data from ioctl(__RTD_ECAN_IOCTL__PREPARE_RECEIVED_MESSAGE) *
 ******************************************************************************/

struct __rtd_ecan_ioctl_prepare_received_message
{

    /*
     * Number of message items in driver's receive queue
     */

    size_t rx_queue_count;

    /*
     * Mask of events which have occurred for a message
     */

    uint   events;
};


enum RTD_ECAN_LED_FLAGS   { RTD_ECAN_LED_RED =1, RTD_ECAN_LED_GREEN=2 };

enum RTD_ECAN_QUEUE_FLAGS { RTD_ECAN_RX_QUEUE=1, RTD_ECAN_TX_QUEUE =2 };


enum
{
    RTD_ECAN_EVENT_SHIFT_RECEIVE         ,
    RTD_ECAN_EVENT_SHIFT_TRANSMIT        ,
    RTD_ECAN_EVENT_SHIFT_ERROR_WARN_LIMIT,
    RTD_ECAN_EVENT_SHIFT_DATA_OVERRUN    ,
    RTD_ECAN_EVENT_SHIFT_WAKE_UP         ,
    RTD_ECAN_EVENT_SHIFT_ERROR_PASSIVE   ,
    RTD_ECAN_EVENT_SHIFT_ARBITRATION_LOST,
    RTD_ECAN_EVENT_SHIFT_BUS_ERROR
};

enum
{
    RTD_ECAN_EVENT_RECEIVE          = 1<<RTD_ECAN_EVENT_SHIFT_RECEIVE         ,
    RTD_ECAN_EVENT_TRANSMIT         = 1<<RTD_ECAN_EVENT_SHIFT_TRANSMIT        ,
    RTD_ECAN_EVENT_ERROR_WARN_LIMIT = 1<<RTD_ECAN_EVENT_SHIFT_ERROR_WARN_LIMIT,
    RTD_ECAN_EVENT_DATA_OVERRUN     = 1<<RTD_ECAN_EVENT_SHIFT_DATA_OVERRUN    ,
    RTD_ECAN_EVENT_WAKE_UP          = 1<<RTD_ECAN_EVENT_SHIFT_WAKE_UP         ,
    RTD_ECAN_EVENT_ERROR_PASSIVE    = 1<<RTD_ECAN_EVENT_SHIFT_ERROR_PASSIVE   ,
    RTD_ECAN_EVENT_ARBITRATION_LOST = 1<<RTD_ECAN_EVENT_SHIFT_ARBITRATION_LOST,
    RTD_ECAN_EVENT_BUS_ERROR        = 1<<RTD_ECAN_EVENT_SHIFT_BUS_ERROR       ,

    RTD_ECAN_EVENT_ALL =
	  RTD_ECAN_EVENT_RECEIVE
	| RTD_ECAN_EVENT_TRANSMIT
	| RTD_ECAN_EVENT_ERROR_WARN_LIMIT
	| RTD_ECAN_EVENT_DATA_OVERRUN
	| RTD_ECAN_EVENT_WAKE_UP
	| RTD_ECAN_EVENT_ERROR_PASSIVE
	| RTD_ECAN_EVENT_ARBITRATION_LOST
	| RTD_ECAN_EVENT_BUS_ERROR
};


/******************************************************************************
 * rtd_ecan_send_command                                                      *
 *                                                                            *
 * Used to pass data into ioctl(__RTD_ECAN_IOCTL__SEND_COMMAND)               *
 *                                                                            *
 * ECAN1000 only                                                              *
 ******************************************************************************/

struct rtd_ecan_send_command
{

    /*
     * Flag to indicate whether or not Transmission Request command should be
     * sent.  A value of 0 means do not send this command.  Any other value
     * means send this commnd.
     */

    int TR;

    /*
     * Flag to indicate whether or not Release Receive Buffer command should be
     * sent.  A value of 0 means do not send this command.  Any other value
     * means send this commnd.
     */

    int RRB;

    /*
     * Flag to indicate whether or not Abort Transmission command should be
     * sent.  A value of 0 means do not send this command.  Any other value
     * means send this commnd.
     */

    int AT;

    /*
     * Flag to indicate whether or not Clear Data Overrun command should be
     * sent.  A value of 0 means do not send this command.  Any other value
     * means send this commnd.
     */

    int CDO;

    /*
     * Flag to indicate whether or not Self Reception Request command should be
     * sent.  A value of 0 means do not send this command.  Any other value
     * means send this commnd.
     */

    int SRR;
};


/******************************************************************************
 * rtd_ecan_status                                                            *
 *                                                                            *
 * Used to return data from ioctl(__RTD_ECAN_IOCTL__GET_STATUS)               *
 ******************************************************************************/

struct rtd_ecan_status
{

    /*
     * Contents of Arbitration Lost Capture Register (ECAN1000).  This is set
     * to 0 on an ECAN527.
     */

    u8_t Arbitration;

    /*
     * Contents of Last Error Code Register (ECAN1000) or Error Code Capture
     * Register (ECAN527)
     */

    u8_t ErrorCode;

    /*=========================================================================
     = The remaining members are flags indicating whether or not a certain    =
     = event occurred.  A value of 0 means the associated event did not       =
     = occur.  Any other value means the associated event occurred.           =
     =========================================================================*/

    /*
     * Is the CAN bus off?
     */

    int BusOff;

    /*
     * Has error counter exceeded limit?
     */

    int Warning;

    /*
     * Was controller woken from sleep mode (ECAN527)?  This is set to 0 on an
     * ECAN1000.
     */

    int WakeUp;

    /*
     * Has the last requested transmission completed successfully?
     */

    int TXOK;

    /*
     * Was a message received successfully (ECAN527)?  This is set to 0 on an
     * ECAN1000.
     */

    int RXOK;

    /*
     * Is controller transmitting a message (ECAN1000)?  This is set to 0 on an
     * ECAN527.
     */

    int TS;

    /*
     * Is controller receiving a message (ECAN1000)?  This is set to 0 on an
     * ECAN527.
     */

    int RS;

    /*
     * Is transmit buffer released/free (ECAN1000)?  This is set to 0 on an
     * ECAN527.
     */

    int TBS;

    /*
     * Was message lost because controller receive queue is full (ECAN1000)?
     * This is set to 0 on an ECAN527.
     */

    int DOS;

    /*
     * Are messages available in controller receive queue (ECAN1000)?  This is
     * set to 0 on an ECAN527.
     */

    int RBS;
};


/******************************************************************************
 * rtd_ecan_message                                                           *
 *                                                                            *
 * Used to pass data into and return data from                                *
 * ioctl(__RTD_ECAN_IOCTL__RECV_MESSAGE) and                                  *
 * ioctl(__RTD_ECAN_IOCTL__SEND_MESSAGE).  Also used to pass messages around  *
 * within driver functions.                                                   *
 ******************************************************************************/

struct rtd_ecan_message
{

    /*
     * Message object for receive or transmit (ECAN527).  A value of 0 means
     * the default object.  Message objects are numbered from 1 to 15, with
     * object 15 being a receive-only object.  This is unused on an ECAN1000.
     */

    u8_t Channel;

    /*
     * Message Identifier octets
     */

    u8_t ID[4];

    /*
     * Message Data Length Code
     */

    u8_t DataLength;

    /*
     * Message Data octets
     */

    u8_t Data[8];

    /*
     * Flag to indicate Extended Frame Format.  A value of 0 means this is a
     * standard frame.  Any other value means this is an extended frame.
     */

    int Extended;

    /*
     * Flag to indicate Remote Frame request.  On an ECAN527, when this is a
     * received message, this will be set to 0.
     */

    int Remote;

    /*
     * Flag to indicate whether or not another message is available.  A value
     * 0 means no message is available.  Any other value means another message
     * is available.
     */

    int NextMsg;
};


/******************************************************************************
 * The following object states only have meaning on an ECAN527                *
 ******************************************************************************/

enum RTD_ECAN_MSG_OBJ_STATE
{
    RTD_ECAN_MO_DISABLED,
    RTD_ECAN_MO_RECEIVE,	/* receive  */
    RTD_ECAN_MO_TRANSMIT,	/* transmit */
    RTD_ECAN_MO_REMOTE_TRANSMIT	/* transmit after receiving remote frame
					whith the same ID */
};


/******************************************************************************
 * rtd_ecan_msg_obj_setup                                                     *
 *                                                                            *
 * Used to pass data into ioctl(__RTD_ECAN_IOCTL__SETUP_MESSAGE_OBJECT)       *
 *                                                                            *
 * ECAN527 only                                                               *
 ******************************************************************************/

struct rtd_ecan_msg_obj_setup
{

    /*
     * State of message object.  Appropriate values are specified above in
     * RTD_ECAN_MSG_OBJ_STATE enum.
     */

    int State;

    /*
     * Message object for receive or transmit.  A value of 0 means the default
     * object.  Message objects are numbered from 1 to 15, with object 15 being
     * a receive-only object.
     */

    u8_t Channel;

    /*
     * Message Identifier octets
     */

    u8_t ID[4];

    /*=========================================================================
     = The remaining members are flags indicating whether or not a certain    =
     = functionality should be enabled.  A value of 0 means the associated    =
     = functionality should not be enabled.  Any other value means the        =
     = associated functionality should be enabled.                            =
     =========================================================================*/

    /*
     * Should the message object be enabled?
     */

    int Valid;

    /*
     * Should the message object use Extended Frame Format?
     */

    int Extended;

    /*
     * Set the Receive Interrupt Enable bit for the message object?
     */

    int RXIE;

    /*
     * Set the Transmit Interrupt Enable bit for the message object?
     */

    int TXIE;

    /*
     * Make message object the default object?
     */

    int MakeDefault;
};  


/******************************************************************************
 * rtd_ecan_filter                                                            *
 *                                                                            *
 * Used to pass data into ioctl(__RTD_ECAN_IOCTL__SET_FILTER) and to pass     *
 * filters around within driver functions.                                    *
 ******************************************************************************/

struct rtd_ecan_filter
{

    /*
     * Acceptance codes.  On an ECAN1000, these will be stored in the
     * Acceptance Code Registers.  On an ECAN527, these are unused.
     */

    u8_t AC[4];

    /*
     * Acceptance masks.  On an ECAN1000, these will be stored in the
     * Acceptance Mask Registers.  On an ECAN527, these will be stored in the
     * Global Mask Standard Registers.
     */

    u8_t AM[4];

    /*
     * Values for Global Mask Extended Registers (ECAN527 only).
     */

    u8_t ME[4];

    /*
     * Values for Message 15 Mask Registers (ECAN527 only).
     */

    u8_t MM[4];

    /*
     * Indicates whether or not to use dual filter mode (ECAN1000 only).
     */

    int DualFilter;

    /*
     * Indicates whether or not Message 15 Mask is for extended frames
     */

    int MMIsExtended;
};


/******************************************************************************
 * rtd_ecan_accounts                                                          *
 *                                                                            *
 * Used to return data from ioctl(__RTD_ECAN_IOCTL__GET_ACCOUNTS) and to      *
 * accumulate internal driver statistics                                      *
 ******************************************************************************/

typedef struct rtd_ecan_accounts
{

    /*
     * Number of bytes read from I/O space of board.
     */

    unsigned long long int port_in;

    /*
     * Number of bytes written to I/O space of board.
     */

    ulonglong port_out;

    /*
     * Number of calls to board_in() driver has made
     */

    ulonglong board_in;

    /*
     * Number of calls to board_out() driver has made
     */

    ulonglong board_out;

    /*
     * Number of controller hard resets performed by driver (ECAN1000 only)
     */

    ulonglong hard_reset;

    /*
     * Number of controller soft resets performed by driver
     */

    ulonglong soft_reset;

    /*
     * Number of messages received from controller
     */

    ulonglong received_messages;

    /*
     * Number of remote messages received from controller (ECAN1000 only)
     */

    ulonglong received_rtr_messages;

    /*
     * Number of message octets received from controller
     */

    ulonglong received_message_octets;

    /*
     * Number of messages lost due to buffer overrun (ECAN527 and ECAN1000) or
     * to message object receive overwrites (ECAN527 only)
     */

    ulonglong lost_messages;

    /*
     * Number of messages sent to controller
     */

    ulonglong transmitted_messages;

    /*
     * Number of remote messages sent to controller
     */

    ulonglong transmitted_rtr_messages;

    /*
     * Number of message octets sent to controller
     */

    ulonglong transmitted_message_octets;

    /*
     * Number of attempts at locking a board structure from interrupt level
     * when the structure was found to be locked elsewhere
     */

    ulonglong try_lock_fail;

    /*
     * Number of attempts at locking a board structure from interrupt level
     * when the structure was found to be unlocked
     */

    ulonglong try_lock_success;

    /*
     * Number of board structure unlocks from interrupt level
     */

    ulonglong try_lock_unlock;

    /*
     * Number of board structure lock operations from non-interrupt level
     */

    ulonglong     lock;

    /*
     * Number of board structure unlock operations from non-interrupt level
     */

    ulonglong   unlock;

    /*
     * Number of all interrupts occurring for a controller
     */

    ulonglong               all_interrupts;

    /*
     * Number of interrupts occurring when a board structure was found to be
     * unlocked
     */

    ulonglong         immediate_interrupts;

    /*
     * Number of interrupts occurring when a board structure was found to be
     * locked
     */

    ulonglong          deferred_interrupts;

    /*
     * Number of interrupts found to be deferred after a board structure was
     * unlocked from non-interrupt level
     */

    ulonglong    taked_deferred_interrupts;

    /*
     * Number of deferred interrupts that were serviced after a board structure
     * was unlocked from non-interrupt level
     */

    ulonglong deferred_serviced_interrupts;

    /*
     * Number of interrupts serviced for a controller
     */

    ulonglong          serviced_interrupts;

    /*
     * Number of receive queue message items allocated
     */

    size_t rx_queue_size;

    /*
     * Number of receive queue message items used
     */

    size_t rx_queue_used;

    /*
     * Number of transmit queue message items allocated
     */

    size_t tx_queue_size;

    /*
     * Number of transmit queue message items used
     */

    size_t tx_queue_used;

    /*
     * Number of microseconds since last time driver statistics were reset
     */

    ulonglong accounting_utime;

} rtd_ecan_accounts_t;


/******************************************************************************
 * rtd_ecan_load_port_bit_dir                                                 *
 *                                                                            *
 * Used to pass data into ioctl(__RTD_ECAN_IOCTL__LOAD_PORT_BIT_DIR)          *
 *                                                                            *
 * ECAN527 only                                                               *
 ******************************************************************************/

typedef struct rtd_ecan_load_port_bit_dir {

    /*=========================================================================
     = All members indicate what direction the appropriate digital I/O port   =
     = bit should have.  A value of 0 means the bit should be set to input.   =
     = Any other value means the bit should be set to output.                 =
     =========================================================================*/

    unsigned char bit7;
    unsigned char bit6;
    unsigned char bit5;
    unsigned char bit4;
    unsigned char bit3;
    unsigned char bit2;
    unsigned char bit1;
    unsigned char bit0;
} rtd_ecan_load_port_bit_dir_t;


#endif /* _ECAN_BASE_IOCTL_H */
